package ru.javadevelop.vegetarian.common;

import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Environment;
import android.os.StatFs;

import java.io.*;

/**
 * Класс для работы с файлами, папками и т.п.
 */
public  class FileUtils {
    private static boolean isStogadeSetted = false;
    private static double NEEDED_FREE_SPACE = 0.2; // Размер необходимого свободного места в гигабайтах

    //******************************************************************************************************************
    public static void saveImageFromStream(Context context, InputStream fileStream, String fileName) throws FileNotFoundException {
        File file = new File(getPath(context, FolderType.IMAGES), fileName);
        FileOutputStream f = new FileOutputStream(file);
        InputStream in = fileStream;

        byte[] buffer = new byte[1024];
        int len1 = 0;
        try
        {
            while ((len1 = in.read(buffer)) > 0)
            {
                f.write(buffer, 0, len1);
            }
            f.close();
        }
        catch (Exception e)
        {
            throw  new RuntimeException(e);
        }
    }

    /**
     * Типы папок для хранения данных.
     * PHOTO — изображения приложения.
     * DATA — папка для данных (БД и т.д.).
     * MEDIA — папка для Avi, mp3
     */
    public static enum FolderType
    {
        IMAGES,   // Папка для изображений
        DATA,    // Папка для данных (БД и т.д.)
        MEDIA    // Папка для Avi, mp3
    }
    //******************************************************************************************************************

    /**
     * Читает текстовый файл. Полезно для чтения, например SQL-скриптов
     * @param path
     * @return
     */
    public static String readRawTextFile(String path)
    {
        InputStream inputStream = FileUtils.class.getResourceAsStream(path);

        ByteArrayOutputStream ostream = new ByteArrayOutputStream();

        byte[] buf = new byte[10240];
        int bytes;
        try {

            while (-1 != (bytes = inputStream.read(buf)))
                ostream.write(buf, 0, bytes);

        } catch (IOException e) {
            return null;
        }
        finally {
            try { inputStream.close(); } catch (IOException e) {}
        }
        return ostream.toString();
    }

    //******************************************************************************************************************
    /**
     * Копирует файл из ресурса на SdCard
     * @param resourceId     Ресурс. Например, R.raw.test
     * @param filePath - путь к файлу, НЕ включая '/sdcard'
     * @param fileName - имя создаваемого файла
     */
    public static void copyFromRawToSdCard(Context context,
                                           int resourceId,
                                           String filePath,
                                           String fileName)
    {

        InputStream rawFile = context.getResources().openRawResource(resourceId);
        File sdCard = Environment.getExternalStorageDirectory();
        File file = new File(sdCard+"/"+filePath, fileName);
        if (!file.exists())
        {
            try
            {
                FileOutputStream fileout = new FileOutputStream(file);
                byte[] buffer = new byte[1024];
                int bufferLength = 0;
                while ((bufferLength = rawFile.read(buffer))>0)
                {
                    fileout.write(buffer, 0 , bufferLength);
                }
                fileout.close();
            } catch (IOException ex)
            {
                ex.printStackTrace();
                System.exit(-1);
            }
        }
    }
    //******************************************************************************************************************

    /**
     * Устанавливает и получает каталог для хранения данных, указанных в параметре folderType
     * @param folderType — тип папки, которая создаётся или берется.
     * @return  Каталог, в котором хранятся нужные данные.
     */
    public static File getPath(Context context, FolderType folderType)
    {
        // Проверяем, было ли ранее установлено хранилище
        if (!isStogadeSetted)
        {  // Если хранилище не было установлено, устанавливаем его
            setSoragePlace(context);
        }

        SharedPreferences prefs = context.getSharedPreferences("X", Context.MODE_PRIVATE);
        // Если в настройках задано хранение на SD-карте
        if (prefs.getBoolean("storeOnExternalSD", false))
        {
            return createAppDirOnSD("/Android/data/" +
                                    context.getApplicationInfo().packageName +
                                    "/files/" +
                                    folderType.toString());
        } else // Если в настройках задано храниение во внутренней памяти
        {
            // проверяем, есть ли место во внутренней памяти
            if (getFreeInternalSpace(context)>=NEEDED_FREE_SPACE)
            {
                return context.getDir(folderType.toString(), Context.MODE_PRIVATE);
            } else
            {
                throw new RuntimeException("There's no deeded free space (" +NEEDED_FREE_SPACE+" Gb)");
            }

        }
    }
    //******************************************************************************************************************
    public static void setSoragePlace(Context context)
    {
        SharedPreferences prefs = context.getSharedPreferences("X", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = prefs.edit();
        // Проверяем, доступно ли вообще внешнее хранилище
        if (checkExternalStorageAvailable())
        {
            // Проверяем, есть ли 1Гб свободного SD-месте
            if (getFreeSDSpace()>=NEEDED_FREE_SPACE)
            {
                editor.putBoolean("storeOnExternalSD", true);
            }
            else // Если 1Гб отсутствует, будем писать на в основную память.
            {
                editor.putBoolean("storeOnExternalSD", false);
            }
        }
        else
        {
            // Устанавливаем в настройки внутреннюю память, как единственно возможную
            editor.putBoolean("storeOnExternalSD", false);
        }
        isStogadeSetted = true;
        editor.commit();
    }
    //******************************************************************************************************************
    /**
     * Узнает, есть ли возможность писать на SD-карту.
     * @return
     */
    private static boolean checkExternalStorageAvailable()
    {
        String state = Environment.getExternalStorageState();

        if (Environment.MEDIA_MOUNTED.equals(state)) {
            // We can read and write the media
            return true;
        } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            // We can only read the media
            return false;
        } else {
            // Something else is wrong. It may be one of many other states, but all we need
            //  to know is we can neither read nor write
            return false;
        }
    }
    //******************************************************************************************************************

    /**
     * Выдает количество свободного места на SD-карте В ГИГАБАЙТАХ
     */
    public static  double getFreeSDSpace()
    {
        StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
        double sdAvailSize = (double)stat.getAvailableBlocks()
                * (double)stat.getBlockSize();
        //One binary gigabyte equals 1,073,741,824 bytes.
        return sdAvailSize / 1073741824;
    }
    //******************************************************************************************************************
    /**
     * Выдает количество свободного места во внутренней памяти В ГИГАБАЙТАХ
     */
    public static double getFreeInternalSpace(Context context)
    {
        File path = Environment.getDataDirectory();
        StatFs stat = new StatFs(path.getPath());
        long blockSize = stat.getBlockSize();
        long availableBlocks = stat.getAvailableBlocks();
        //One binary gigabyte equals 1,073,741,824 bytes.
        return (availableBlocks * blockSize) / 1073741824 ;
    }
    //******************************************************************************************************************
    public static File createAppDirOnSD(String filePath)
    {
        File sdCard = Environment.getExternalStorageDirectory();
        File file = new File(sdCard+"/" + filePath);
        file.mkdirs();
        return file;
    }
    //******************************************************************************************************************

    public static void deleteFile(String path)
    {
        File file = new File(path);
        file.delete();
    }

}
